/* * Copyright (C) 2000-2012 InfoChamp System Corporation * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.gk.engine.client.event; import java.util.Iterator; import java.util.List; import java.util.Map; import jfreecode.gwt.event.client.bus.EventBusIfc; import jfreecode.gwt.event.client.bus.JsonConvert; import org.gk.engine.client.IEngine; import org.gk.engine.client.build.XComponent; import org.gk.engine.client.build.js.XJavaScript; import org.gk.engine.client.event.attrib.IAttribute; import org.gk.engine.client.exception.GKEngineException; import org.gk.engine.client.exception.InvalidValueException; import org.gk.engine.client.i18n.EngineMessages; import org.gk.engine.client.utils.ComponentUtils; import org.gk.ui.client.com.form.gkMap; import com.extjs.gxt.ui.client.event.BaseEvent; import com.extjs.gxt.ui.client.event.EventType; import com.extjs.gxt.ui.client.widget.Component; import com.extjs.gxt.ui.client.widget.Info; import com.google.gwt.core.client.JavaScriptObject; import com.google.gwt.json.client.JSONArray; import com.google.gwt.json.client.JSONObject; /** * 事件處理器 * * <pre> * 可使用的事件種類: * pub:發佈本地端事件 * bean:調用Spring元件,發佈遠端事件 * file:讀取檔案(當使用靜態網頁才能使用) * sub:訂閱事件 * com:直接改變另一元件 * show:顯示訊息 * js:編寫javascript * </pre> * * @author i23250 * @since 2010/9/24 */ public abstract class EventHandler implements IHandler { private final static String JAVASCRIPT = "_gk_js_"; protected EventBusIfc bus = IEngine.bus; // 存放能處理的事件指令 (pub,sub,file,bean...) private static Map<String, IHandler> handlerGroup = EventFactory .createHandlerGroup(); // 存放能存取的屬性 (id,value,width...) private static Map<String, IAttribute> attributeGroup = EventFactory .createAttributeGroup(); // 存放GXT的事件種類 private static Map<String, EventType> eventTypeGroup = EventFactory .createEventTypeGroup(); /** * 根據輸入的cmd,取得對應的處理器介面 * * @param cmd * @return IHandler */ private static IHandler getHandler(String cmd) { if (!handlerGroup.containsKey(cmd)) { throw new GKEngineException( EngineMessages.msg.error_handlerNotFound(cmd)); } return handlerGroup.get(cmd); } /** * 根據輸入的cmd,取得對應的屬性介面 * * @param cmd * @return IAttribute */ private static IAttribute getAttribute(String cmd) { String key = cmd.toLowerCase(); if (!attributeGroup.containsKey(key)) { // 找不到對應的屬性,則拋出訊息(不可丟出exception會導致之後的屬性沒有設定到) Info.display(EngineMessages.msg.warning(), EngineMessages.msg.error_attributeNotImplement(cmd)); } return attributeGroup.get(key); } /** * 根據輸入的eventType,取得對應的事件種類 * * @param eventType * @return EventType */ public static EventType getEventType(String eventType) { String key = eventType.toLowerCase(); if (!eventTypeGroup.containsKey(key)) { Info.display(EngineMessages.msg.warning(), EngineMessages.msg.error_eventTypeNotSupport(eventType)); } return eventTypeGroup.get(key); } /** * 此方法由EventCenter調用,開始執行事件解析 指派對應的Handler進行處理 * * @param xComId * @param ed * @param xCom * @param be */ public static void doProcess(String xComId, EventData ed, XComponent xCom, BaseEvent be) { IHandler handler = EventHandler.getHandler(ed.getCmd()); handler.process(xComId, ed.getSources(), ed.getTargets(), xCom, be); } /** * 取得元件屬性值 * * @param id * @return Object */ public static Object getAttributeValue(String id) { Object value = null; String[] dot = id.split(IEventConstants.SPLIT_DOT); Component com = ComponentUtils.findComponent(dot[0]); if (com != null) { if (dot.length == 2) { value = getAttributeValue(com, dot[1]); } else if (dot.length == 1) { value = getAttributeValue(com); } } return value; } /** * 取得元件屬性值 * * @param com * @param attribute * @return Object */ public static Object getAttributeValue(Component com, String attribute) { Object value = null; IAttribute attrib = getAttribute(attribute); if (attrib != null) { value = attrib.getAttributeValue(com); } return value; } /** * 取得元件屬性值 * * @param com * @return Object */ public static Object getAttributeValue(Component com) { return getAttributeValue(com, IEventConstants.ATTRIB_VALUE); } /** * 設定元件屬性值 * * @param id * @param value */ public static void setAttributeValue(String id, Object value) { // 若id為_gk_js_,則直接執行JavaScript腳本 (當後續種類變多時,再重構增加"預設行為分派類") if (id.equals(JAVASCRIPT)) { new XJavaScript(value + "").createScriptNodeToExecute(); } else { String[] dot = id.split(IEventConstants.SPLIT_DOT); Component com = ComponentUtils.findComponent(dot[0]); if (com != null) { // 判斷是否有指定元件的屬性,例如grid1.value if (dot.length == 2) { setAttributeValue(com, dot[1], value); } else if (dot.length == 1) { setAttributeValue(com, value); } } } } /** * 設定元件屬性值 * * @param com * @param attribute * @param value */ public static void setAttributeValue(Component com, String attribute, Object value) { IAttribute attrib = getAttribute(attribute); if (attrib != null) { try { attrib.setAttributeValue(com, value); } catch (Exception e) { throw new InvalidValueException( EngineMessages.msg.error_invalidValue(com.getId(), value)); } } } /** * 設定元件屬性值 * * @param com * @param value */ public static void setAttributeValue(Component com, Object value) { setAttributeValue(com, IEventConstants.ATTRIB_VALUE, value); } protected Object eval(String content) { Object result = null; if (JsonConvert.isJSONString(content)) { result = JsonConvert.jsonString2Object(content); } else { result = doEval(content); } return result; } private native static Object doEval(String content)/*-{ var result = $wnd.eval(content); if (typeof (result) == 'boolean') { result = @java.lang.Boolean::valueOf(Z)(result); } else if (typeof (result) == 'number') { result = @java.lang.Double::valueOf(D)(result); } return result; }-*/; /** * 將傳入的events,根據類型合併成一eventId字串 * * @param events * @return String */ protected String prepareEventId(List events) { StringBuffer eventId = new StringBuffer(""); if (!events.isEmpty()) { for (Object value : events) { EventValue ev = EventFactory.convertToEventValue(value); String content = ev.getContent(); switch (ev.getType()) { case EXPR: eventId.append(eval(content)); break; case ID: if (content.matches("\\w+\\.\\w+")) { eventId.append(content); } else { eventId.append(getAttributeValue(content)); } break; case STRING: eventId.append(content); default: break; } } } return eventId.toString(); } /** * 將傳入的events,根據類型整理並存入Map資料中 * * @param srcId * @param events * @return Map */ protected Map prepareInfo(String srcId, List events) { Map info = new gkMap(); // 記錄此遠端事件是由哪個ComponentId發起的 info.put("src", srcId); info.put("url", getURL()); if (!events.isEmpty()) { for (Iterator it = events.iterator(); it.hasNext();) { EventValue ev = EventFactory.convertToEventValue(it.next()); String content = ev.getContent(); switch (ev.getType()) { case EXPR: info.put(srcId, eval(content)); break; case ID: info.put(content, getAttributeValue(content)); break; case STRING: info.put(srcId, content); default: break; } } } return info; } /** * 取得URL * * @return String */ public static native String getURL()/*-{ return $wnd.location.href; }-*/; /** * 調用JavaScript的function * * @param func * @param data */ protected void invokeFunction(JavaScriptObject func, Object data) { if (data instanceof String) { invokeFunction(func, (String) data); } else if (data instanceof Map) { JSONObject json = JsonConvert.toJSONObject((Map) data); invokeFunction(func, json.getJavaScriptObject()); } else if (data instanceof List) { JSONArray json = JsonConvert.toJSONArray((List) data); invokeFunction(func, json.getJavaScriptObject()); } else { invokeFunction(func, data + ""); } }; private static native void invokeFunction(JavaScriptObject func, JavaScriptObject data)/*-{ func(data); }-*/; private static native void invokeFunction(JavaScriptObject func, String data)/*-{ func(data); }-*/; }